package com.example.store;

import com.example.model.Device;
import com.example.model.DeviceType;
import com.example.service.Tenant;
import com.example.service.TenantAwareDataSourceFactory;
import org.apache.ignite.cache.store.CacheStoreAdapter;
import org.apache.ignite.lang.IgniteBiInClosure;

import javax.cache.Cache;
import javax.cache.integration.CacheWriterException;
import javax.sql.DataSource;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;

public class DeviceTypeCacheStore extends CacheStoreAdapter<Long, DeviceType> {
//    private final transient DataSource dataSource;
    private final Tenant tenant;

    public DeviceTypeCacheStore(Tenant tenant) {

        this.tenant = tenant;
    }

    private DataSource getDataSource(){
        return new TenantAwareDataSourceFactory(tenant).create();
    }

    @Override
    public DeviceType load(Long key) {
        try (Connection conn = getDataSource().getConnection()) {
            try (PreparedStatement st = conn.prepareStatement(
                    "SELECT * FROM " + tenant.getSchema() + ".device_type WHERE id = ?")) {
                st.setLong(1, key);
                ResultSet rs = st.executeQuery();
                if (rs.next()) {
                    return mapResultSetToDevice(rs);
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return null;
    }

    @Override
    public void write(Cache.Entry<? extends Long, ? extends DeviceType> entry) {
        DeviceType device = entry.getValue();
        try (Connection conn = getDataSource().getConnection()) {
            try (PreparedStatement st = conn.prepareStatement(
                    "INSERT INTO " + tenant.getSchema() + ".device_type (id, name, description, active) " +
                            "VALUES (?, ?, ?, ?) " +
                            "ON DUPLICATE KEY UPDATE " +
                            "name=?, description=?, active=?")) {

                st.setLong(1, device.getId());
                st.setString(2, device.getName());
                st.setString(3,device.getDescription());
                st.setBoolean(4, device.getActive());

                st.setString(5, device.getName());
                st.setString(6,device.getDescription());
                st.setBoolean(7, device.getActive());

                st.executeUpdate();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void delete(Object key) throws CacheWriterException {

    }

    @Override
    public void loadCache(IgniteBiInClosure<Long, DeviceType> clo, Object... args) {
        try (Connection conn = getDataSource().getConnection()) {
            try (PreparedStatement st = conn.prepareStatement(
                    "SELECT * FROM " + tenant.getSchema() + ".device_type")) {
                ResultSet rs = st.executeQuery();
                while (rs.next()) {
                    DeviceType device = mapResultSetToDevice(rs);
                    clo.apply(device.getId(), device);
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    private DeviceType mapResultSetToDevice(ResultSet rs) throws SQLException {
        DeviceType deviceType = new DeviceType();
        deviceType.setId(rs.getLong("id"));
        deviceType.setName(rs.getString("name"));
        deviceType.setDescription("description");
        deviceType.setActive(rs.getBoolean("active"));
        return deviceType;
    }
}